package dnl.dev.memlog.sampler;

import java.io.File;
import java.io.IOException;
import java.util.Date;

import org.apache.commons.io.FileUtils;

import dnl.cmd.CommandExecution;
import dnl.cmd.CommandExecutionFactory;
import dnl.dev.memlog.MemlogProject;

/**
 * 
 * @author Daniel Ore
 * 
 */
public class MemSampler {

	public static final String HISTO_FILE_EXT = ".mem.histo";
	private String processId;
	private File histogramsDir;
	private SamplerConfiguration configuration;

	private MemlogProject memlogProject;

	public MemSampler(String processId, MemlogProject memlogProject) {
		this.processId = processId;
		configuration = new SamplerConfiguration();
		this.memlogProject = memlogProject;
	}

	public MemSampler(String processId, SamplerConfiguration configuration,
			MemlogProject memlogProject) {
		this.processId = processId;
		this.configuration = configuration;
		this.memlogProject = memlogProject;
	}

	public void startSamplingThread() {
		System.out.println("start sampling processid=" + processId);
		Runnable r = new Runnable() {
			@Override
			public void run() {
				while (true) {
					sampleImpl(null);
					try {
						Thread.sleep(configuration.getSamplingFrequencySec() * 1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		};
		Thread t = new Thread(r);
		t.start();
	}

	public void takeSample(String name) {
		sampleImpl(name);
	}

	private void sampleImpl(String id) {
		assertHistogramsDir();

		File histoFile = null;
		if (id != null) {
			String fname = id + HISTO_FILE_EXT;
			histoFile = new File(histogramsDir, fname);
		} else {
			histoFile = resolveFileForNewSample();
		}

		CommandExecution jmap = CommandExecutionFactory.createLocalCommandExecution("jmap",
				"-histo", processId);
		System.out.println("taking sample - " + histoFile.getName());
		jmap.executeCommand(true);
		if (jmap.hasCompleted()) {
			try {
				FileUtils.writeStringToFile(histoFile, jmap.getOutput());
				memlogProject.getSamplingInfo().registerDate(histoFile.getName(), new Date());
				memlogProject.save();
			} catch (IOException e) {
				e.printStackTrace();
			}
		} else {
			System.err.println("Error executing jmap:");
			System.err.println(jmap.describeWithErrors());
		}
	}

	private File resolveFileForNewSample() {
		File histFile = null;
		for (int i = 1; histFile == null; i++) {
			File f = new File(histogramsDir, i+HISTO_FILE_EXT);
			if (!f.exists()) {
				histFile = f;
			}
		}
		return histFile;
	}

	private File assertHistogramsDir() {
		if (histogramsDir == null) {
			String samplingStorageDir = memlogProject.getProjectDirPath();
			File dir = null;
			if (samplingStorageDir == null) {
				for (int i = 1; dir == null; i++) {
					File f = new File("mem.sample." + i);
					if (!f.exists()) {
						dir = f;
					}
				}
				histogramsDir = dir;
			} else {
				histogramsDir = new File(samplingStorageDir);
				if (!histogramsDir.exists()) {
					try {
						FileUtils.forceMkdir(histogramsDir);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
		return histogramsDir;
	}

}
